/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/
package ichain

import (
	reqContext "context"

	"git.cloud.inspur.com/ichain/ichain-protos-go/common"
	pb "git.cloud.inspur.com/ichain/ichain-protos-go/inode"
	"github.com/golang/protobuf/proto"
	"github.com/pkg/errors"
)

// ProposalProcessor 提案背书
type ProposalProcessor interface {
	ProcessTransactionProposal(reqContext.Context, ProcessProposalRequest) (*TransactionProposalResponse, error)
}

// TxnHeaderOptions 交易头选择项
type TxnHeaderOptions struct {
	Nonce   []byte // 随机数
	Creator []byte // 交易创建者
}

// TxnHeaderOpt 构建交易头选择项
type TxnHeaderOpt func(*TxnHeaderOptions)

func WithNonce(nonce []byte) TxnHeaderOpt {
	return func(options *TxnHeaderOptions) {
		options.Nonce = nonce
	}
}

func WithCreator(creator []byte) TxnHeaderOpt {
	return func(options *TxnHeaderOptions) {
		options.Creator = creator
	}
}

// ProposalSender 提供了提案操作的接口: 创建提案、发送提案
type ProposalSender interface {
	CreateTxProposalWithHeader(header TransactionHeader, request ContractInvokeRequest) (*TransactionProposal, error)
	CreateTxProposal(request ContractInvokeRequest) (*TransactionProposal, error)
	SendTxProposal(proposal *TransactionProposal, targets []Inode) ([]*TransactionProposalResponse, error)
}

// TransactionID 交易id
type TransactionID string

const EmptyTransactionID = TransactionID("")

// SystemChain 系统链
const SystemChain = ""

// TransactionHeader 交易头信息接口，包括交易id，创建者证书，随机数、链id
type TransactionHeader interface {
	TransactionID() TransactionID
	Creator() []byte
	Nonce() []byte
	ChainID() string
}

// ContractInvokeRequest 合约调用请求
// nolint: maligned
type ContractInvokeRequest struct {
	ContractID   string
	Lang         pb.ContractSpec_Type
	TransientMap map[string][]byte
	Fcn          string
	Args         [][]byte
	IsInit       bool
}

// TransactionProposal 对提案pb的一次封装
type TransactionProposal struct {
	TxnID TransactionID
	*pb.Proposal
}

// ProcessProposalRequest 处理提案的请求
type ProcessProposalRequest struct {
	SignedProposal *pb.SignedProposal
}

// TransactionProposalResponse 封装的提案回复
type TransactionProposalResponse struct {
	Endorser string
	// Status 背书状态
	Status int32
	// ContractStatus 合约状态
	ContractStatus int32
	*pb.ProposalResponse
}

func (txr *TransactionProposalResponse) CreateCommonBlock() (*common.Block, error) {
	response := common.Block{}
	err := proto.Unmarshal(txr.ProposalResponse.GetResponse().Payload, &response)
	if err != nil {
		return nil, errors.Wrap(err, "unmarshal of transaction proposal response failed")
	}
	return &response, err
}
